<template>
  <div class="containner">
    <div v-if="startChat" ref="conversationRef" class="conversation-area">
      <template v-for="(msg, idx) in messages" :key="idx">
        <McBubble v-if="msg.from === 'user'" :align="'right'">
          <McMarkdownCard :content="msg.content" :theme="theme"></McMarkdownCard>
        </McBubble>
        <template v-else>
          <div v-if="msg.loading && !msg.isStop">
            <div> <i class="icon-loading"></i> 正在回答: </div>
          </div>
           <div v-else>
            <div v-if="msg.isStop"><i class="icon-information"></i> 暂停回答 </div>
            <div v-else><i class="icon-to-do success-icon"></i> 完成回答: </div>
          </div>
          <McBubble>
            <McMarkdownCard :content="msg.content" :theme="theme">
              <template #header="{ codeBlockData }">
                <div class="header-container">
                  <div class="header-left">
                  </div>
                  <div class="header-right">
                    <d-tooltip position="left" content="插入">
                      <i class="icon-insert" @click="insertCodeAtCursor(codeBlockData)"></i>
                    </d-tooltip>
                    <d-tooltip position="left" content="复制">
                      <i class="icon-copy-new" @click="copyText(codeBlockData)"></i>
                    </d-tooltip>
                  </div>
                </div>
              </template>
            </McMarkdownCard>
          </McBubble>
        </template>
      </template>
    </div>
    <div v-else class="welcome-page">
      <McIntroduction :logo-img="logo2Png" title="HarmonyPilot" sub-title="Hi，欢迎使用 HarmonyPilot" :description="[
        'HarmonyPilot（鸿蒙领航员，简称“鸿派”）。',
        '是一个为鸿蒙开发者提供沉浸式AI使用体验的服务或者工具，',
        '提供代码生成、智能问答、测试辅助、代码检测等功能。',
        '并通过智能Agent，在应用、外设驱动、设备开发等领域，',
        '提供自主编排、工程生成、智能调测等能力，提升开发者的体验和效率。',
      ]" class="headerIcon2x"></McIntroduction>
    </div>
    <div class="new-convo-button">
      <div class="agent-knowledge">
        <d-dropdown :position="['top']" @toggle="(val) => (isAgentOpen = val)">
          <div class="agent-wrapper">
            <img :src="logoPng" />
            <span>{{ selectedAgent.label }}</span>
            <i class="icon-infrastructure"></i>
            <i :class="['icon-chevron-down-2', { 'is-open': isAgentOpen }]"></i>
          </div>
        </d-dropdown>
      </div>
      <d-button icon="icon-stop" variant="solid" color="secondary" @click="stopResponse"
        v-if="isStreaming">停止回答</d-button>
      <d-button icon="add" shape="circle" title="新建对话" size="sm" @click="onNewConvo" />
    </div>
    <div style="padding: 10px 12px 12px 12px">
      <McInput :value="inputValue" :maxLength="2000" @change="(e) => (inputValue = e)" @submit="onSubmit">
        <template #head v-if="showHighlightedCode">
          <div class="appendix-wrap">
            <div class="appendix-item">
              <span> {{ highlightedCode.fsPath }}</span>
              <span style="margin-left:5px;"> {{ highlightedCode.range }}</span>
              <i class="icon-code-editor-close" @click="highlightedCodeClick()"></i>
            </div>
          </div>
        </template>
        <template #extra>
          <div class="input-foot-wrapper">
            <div class="input-foot-left">
              <span class="input-foot-maxlength">{{ inputValue.length }}/2000</span>
            </div>
            <div class="input-foot-right">
              <d-button icon="op-clearup" shape="round" :disabled="!inputValue" @click="inputValue = ''">清空输入</d-button>
            </div>
          </div>
        </template>
      </McInput>
    </div>
  </div>
</template>

<script setup lang="ts">
import { nextTick, onMounted, ref, watch } from 'vue';
import { ThemeServiceInit, devuiLightTheme, devuiDarkTheme } from 'devui-theme';
import 'vue-devui/button/style.css';
import { marked } from 'marked';
const isStreaming = ref(false);
const controller = ref(new AbortController()); // 存储中断控制器
const logoPng = ref(`${window.staticPath}/resource/logo/Hi.svg`);
const logo2Png = ref(`${window.staticPath}/resource/logo/Hi.svg`);
// 初始是 infinityTheme 无限主题
const themeService = ThemeServiceInit(
  {
    'ide-light': devuiLightTheme,
    'ide-dark': devuiDarkTheme,
  },
  'ide-dark'
);
const theme = ref('dark');
const isAgentOpen = ref(false);
const conversationRef = ref();
const startChat = ref(false);
const autoScrollEnabled = ref(true);
const scrollThreshold = ref(50);
const agentList = ref([
  { label: 'MateChat', value: 'matechat', active: true },
  { label: 'InsCode', value: 'inscode' },
]);
const selectedAgent = ref(agentList.value[0]);
const onNewConvo = () => {
  startChat.value = false;
  messages.value = [];
  deepseekMessages.value = [];
};
const stopResponse = () => {
  messages.value[messages.value.length - 1].isStop = true;
  messages.value[messages.value.length - 1].loading = false;
  if (controller.value) {
    controller.value.abort(); // 触发请求中断‌:ml-citation{ref="7" data="citationList"}
    controller.value = new AbortController();
    isStreaming.value = false;
  }
};
const inputValue = ref('');
const highlightedCode = ref({
  fsPath: '',
  contents: '',
  range: '',
  orginContents: ''
});
const showHighlightedCode = ref(false);
// @ts-ignore
const inputFootIcons = [
  { icon: 'icon-at', text: '智能体' },
  { icon: 'icon-standard', text: '词库' },
  { icon: 'icon-add', text: '附件' },
];
const messages = ref([]);
const deepseekMessages = ref([]);
// @ts-ignore
const onInputIconClick = (e) => {
  if (e.icon === 'icon-at') {
    inputValue.value += `@${selectedAgent.value.label}`;
  }
};
const onSubmit = (evt) => {
  if (isStreaming.value) {
    window?.vscode.postMessage({ messageType: 'wait', data: '请等待上一次回答完成后再进行操作'});
    return;
  }
  isStreaming.value = true;
  inputValue.value = '';
  if (!messages.value.length) {
    startChat.value = true;
  }
  let sendStr = '';
  let displayStr = '';
  if (showHighlightedCode.value) {
    sendStr = highlightedCode.value.orginContents + evt;
    const fsPath = highlightedCode.value.fsPath.replace('.','.​');
    displayStr = `**${fsPath}${highlightedCode.value.range}**\n
    
    \n${evt}`;
  } else {
    sendStr = evt;
    displayStr = evt;
  }
  // 用户发送消息
  messages.value.push({
    from: 'user',
    content: displayStr,
    avatarPosition: 'side-right',
  });
  deepseekMessages.value.push({
    role: 'user',
    content: sendStr
  });
  nextTick(() => {
    if (autoScrollEnabled.value) {
      scrollToBottom();
    }
  });
  fetchData();
};
const scrollToBottom = () => {
  conversationRef.value?.scrollTo({
    top: conversationRef.value.scrollHeight,
    behavior: 'smooth',
  });
}
const themeChange = (isDark: true) => {
  if (themeService) {
    theme.value = isDark  ? 'dark' : 'light';
    themeService.applyTheme(isDark ? devuiDarkTheme : devuiLightTheme);
  }
}
watch(() => startChat.value, (newValue) => {
  if (newValue) {
    setTimeout(() => {
      if (conversationRef.value) {
        conversationRef.value.addEventListener('scroll', () => {
          const isNearBottom = conversationRef.value.scrollTop + conversationRef.value.clientHeight >= conversationRef.value.scrollHeight - scrollThreshold.value;
          autoScrollEnabled.value = isNearBottom;
        });
      }
    });
  }
});
onMounted(() => {
  // Webview前端代码
  window.addEventListener('message', event => { 
    const message = event.data;
    switch (message.messageType) {
      case 'highlightedCode':
        showHighlightedCode.value = true;
        const codeData = message.data.rangeInFileWithContents;
        renderHighlightedCode(codeData);
        break;
      case 'themeChange':
        themeChange(message.data.isDark);
        break; 
    }
  });
  window.addEventListener('load', () => {
    window?.vscode.postMessage({ messageType: 'webviewLoaded', data: '' });
  });
});

function renderHighlightedCode({ filepath, range, contents }) {
  const filePathInfo = decodeURIComponent(filepath.split('/')[filepath.split('/').length - 1]);
  highlightedCode.value = {
    fsPath: filePathInfo,
    contents: getCodeHtml(contents),
    orginContents: contents,
    range: `(${range.start.line + 1}-${range.end.line + 1})`
  };
}
const getCodeHtml = (contents) => {
  const codeWrapper = '```';
  const language = 'vue';
  const markedStr = marked.parse(`${codeWrapper}${language}\r\n${contents}\r\n${codeWrapper}`);
  return appendCodeToTarget(markedStr, {
    needCodeOperateBar: false,
    minCodeLine: 3,
    isExpand: false
  });
};
// @ts-ignore
const appendCodeToTarget = (markedStr, data = {}) => {
  const container = document.createElement('div');
  container.innerHTML = markedStr;
  return container.innerHTML;
}

const fetchData = async () => {
  try {
    highlightedCodeClick();
    messages.value.push({
      from: 'ai-model',
      content: '',
      avatarPosition: 'side-left',
      loading: true,
      isStop: false,
    });
    const response = await fetch('https://api.deepseek.com/v1/chat/completions', {
      method: 'POST',
      headers: {
        'Authorization': `Bearer sk-37addc2257584318ba5e300d38da7305`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        model: "deepseek-chat",
        messages: deepseekMessages.value,
        stream: true
      }),
      signal: controller.value.signal
    });
    const reader = response.body.getReader();
    const decoder = new TextDecoder();
    let deepseekResponseInfo = '';
    while (isStreaming.value) {
      const { done, value } = await reader.read();
      if (done) {
        deepseekResponseInfo = messages.value[messages.value.length - 1].content;
        deepseekMessages.value.push({
          role: 'assistant',
          content: deepseekResponseInfo
        });
        break;
      }
      const chunk = decoder.decode(value);
      const jsonChunks = chunk.split('\n\n').filter(Boolean);
      for (const chunk of jsonChunks) {
        if (chunk === 'data: [DONE]') {
           messages.value[messages.value.length - 1].loading = false;
          break;
        }
        const data = JSON.parse(chunk.replace('data: ', ''));
        const content = data.choices[0]?.delta?.content || '';
        const chatId = data.id;
        messages.value[messages.value.length - 1].content += content;
        messages.value[messages.value.length - 1].id = chatId;
        nextTick(() => {
          if (autoScrollEnabled.value) {
            scrollToBottom();
          }
        });
      }
    }

  } catch (err) {
    if (err.name === 'CanceledError') {
      console.log('用户主动终止');
    }
  } finally {
    isStreaming.value = false;
  }
};
const highlightedCodeClick = () => {
  showHighlightedCode.value = false;
  highlightedCode.value = {
    fsPath: '',
    contents: '',
    orginContents: '',
    range: ''
  };
};
const insertCodeAtCursor = (codeBlockData) => {
  window?.vscode.postMessage({ messageType: 'insertCode', data: codeBlockData });
};

const copyText = (codeBlockData) => {
  window?.vscode.postMessage({ messageType: 'copyText', data: codeBlockData });
};

</script>

<style scoped>
.containner {
  min-width: 320px;
  display: flex;
  flex-direction: column;
  width: 100%;
  height: 100vh;

  .header-wrapper {
    padding: 12px 16px;
  }

  .conversation-area,
  .welcome-page {
    flex: 1;
    display: flex;
    flex-direction: column;
    overflow: auto;
    padding: 20px 12px;
  }

  .conversation-area {
    gap: 8px;
    scrollbar-gutter: stable;

  }

  .conversation-area,
  .welcome-page {
    scrollbar-width: thin;  /* 可选值：auto | thin | none */
  }

  .welcome-page {
    gap: 24px;
    justify-content: center;
  }

  .guess-question {
    width: 100%;
    padding: 16px 12px;
    border-radius: var(--devui-border-radius-card);
    background-color: var(--devui-gray-form-control-bg);

    .guess-title {
      display: flex;
      justify-content: space-between;
      align-items: center;
      color: var(--devui-text);
      margin-bottom: 12px;

      &>div:first-child {
        font-weight: 700;
        font-size: var(--devui-font-size);
      }

      &>div:last-child {
        font-size: var(--devui-font-size-sm);
        cursor: pointer;

        span {
          margin-left: 4px;
        }
      }
    }

    .guess-content {
      display: flex;
      align-items: center;
      flex-wrap: wrap;
      gap: 8px;

      span {
        font-size: var(--devui-font-size-sm);
        color: var(--devui-text);
        padding: 4px 12px;
        border-radius: var(--devui-border-radius-full);
        background-color: var(--devui-gray-form-control-hover-bg);
        cursor: pointer;
      }
    }
  }

  .bubble-bottom-operations {
    margin-top: 8px;

    i {
      padding: 4px;
      border-radius: 4px;
      cursor: pointer;

      &:hover {
        background-color: var(--devui-icon-hover-bg);
      }
    }
  }

  .new-convo-button {
    padding: 0 12px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    height: 39px;
    gap: 4px;
  }

  :deep(.simple-prompt .mc-list) {
    justify-content: unset;
  }

  :deep(.intro-prompt .mc-list) {
    justify-content: center;
  }

  .operations {
    i {
      padding: 4px;
      border-radius: 4px;
      cursor: pointer;

      &:hover {
        background: var(--devui-global-bg);
      }
    }
  }

  .agent-knowledge {
    display: flex;
    align-items: center;

    .agent-wrapper {
      display: flex;
      align-items: center;
      padding: 4px 8px;
      border-radius: var(--devui-border-radius-full);
      background-color: var(--devui-area);
      cursor: pointer;

      img {
        width: 16px;
        height: 16px;
        margin-right: 4px;
      }

      span {
        font-size: var(--devui-font-size);
        color: var(--devui-text);
        margin-right: 8px;
      }

      i {
        font-size: var(--devui-font-size);
        color: var(--devui-text);
        transition: transform 0.3s ease-in-out;

        &:last-child {
          margin-left: 4px;
        }
      }

      .is-open {
        transform: rotate(180deg);
      }
    }

    .agent-knowledge-dividing-line {
      width: 1px;
      height: 14px;
      margin: 0 12px;
      background-color: var(--devui-line);
    }

    .knowledge-wrapper {
      font-size: var(--devui-font-size);
      color: var(--devui-text);
      cursor: pointer;

      span {
        margin-left: 4px;
      }
    }
  }

  .input-foot-wrapper {
    display: flex;
    justify-content: space-between;
    align-items: center;
    width: 100%;
    height: 100%;
    margin-right: 8px;

    .input-foot-left {
      display: flex;
      align-items: center;
      gap: 8px;

      span {
        font-size: var(--devui-font-size-sm);
        color: var(--devui-text);
        cursor: pointer;
      }


      .input-foot-maxlength {
        font-size: var(--devui-font-size-sm);
        color: var(--devui-aide-text);
      }
    }

    .input-foot-right {
      &>*:not(:first-child) {
        margin-left: 8px;
      }
    }
  }
   .success-icon {
    color: #5CB300;
   }
  .headerIcon :deep(.mc-header-logo) {
    height: 32px;
    width: 32px;
  }

  :deep(.headerIcon2x) {
    img {
      height: 64px;
      width: 64px;
    }
  }



}

.input-foot-left {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: var(--devui-font-size-sm);
  color: var(--devui-text);

  i {
    margin-right: 4px;
  }
}

.appendix-wrap {
  display: flex;
  padding: 4px 8px;

  .appendix-item {
    padding: 4px;
    border-radius: var(--devui-border-radius);
    background-color: var(--devui-area);

    i {
      margin-left: 10px;
      cursor: pointer;
    }
  }
}

:deep(.mc-code-block-dark) pre code.hljs,
:deep(.mc-code-block-light) pre code.hljs{
    scrollbar-width: thin;
}
</style>